package com.eduagent.xwqeduagent.controller;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import com.eduagent.xwqeduagent.common.BaseResponse;
import com.eduagent.xwqeduagent.common.ResultUtils;
import com.eduagent.xwqeduagent.exception.BusinessException;
import com.eduagent.xwqeduagent.exception.ErrorCode;
import com.eduagent.xwqeduagent.utils.oj.JudgeLanguage;
import com.eduagent.xwqeduagent.utils.oj.JudgeService;
import com.eduagent.xwqeduagent.utils.oj.JudgeSubmission;
import com.eduagent.xwqeduagent.utils.oj.JudgeSubmissionResponse;

/**
 * 在线评测系统控制器
 */
@RestController
@RequestMapping("/api/judge")
public class JudgeController {
    private static final Logger logger = LoggerFactory.getLogger(JudgeController.class);

    @Autowired
    private JudgeService judgeService;

    /**
     * 获取支持的编程语言列表
     * @return 支持的语言列表
     */
    @GetMapping("/languages")
    public BaseResponse<Map<String, Integer>> getSupportedLanguages() {
        try {
            Map<String, Integer> languages = judgeService.getSupportedLanguages();
            return ResultUtils.success(languages);
        } catch (Exception e) {
            logger.error("获取支持的编程语言失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取支持的编程语言失败: " + e.getMessage());
        }
    }

    /**
     * 提交代码进行评测
     * @param sourceCode 源代码
     * @param languageId 语言ID
     * @param stdin 标准输入
     * @param expectedOutput 期望输出
     * @param wait 是否等待结果
     * @return 评测结果
     */
    @PostMapping("/submit")
    public BaseResponse<JudgeSubmissionResponse> submitCode(
            @RequestParam("source_code") String sourceCode,
            @RequestParam("language_id") Integer languageId,
            @RequestParam(value = "stdin", required = false, defaultValue = "") String stdin,
            @RequestParam(value = "expected_output", required = false, defaultValue = "") String expectedOutput,
            @RequestParam(value = "wait", defaultValue = "true") boolean wait) {
        
        try {
            JudgeSubmissionResponse response = judgeService.submitCode(sourceCode, languageId, stdin, expectedOutput, wait);
            return ResultUtils.success(response);
        } catch (IOException e) {
            logger.error("提交代码评测失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "提交代码评测失败: " + e.getMessage());
        }
    }
    
    /**
     * 提交代码进行评测（使用语言名称）
     * @param sourceCode 源代码
     * @param language 语言名称
     * @param stdin 标准输入
     * @param expectedOutput 期望输出
     * @param wait 是否等待结果
     * @return 评测结果
     */
    @PostMapping("/submit-by-language")
    public BaseResponse<JudgeSubmissionResponse> submitCodeByLanguage(
            @RequestParam("source_code") String sourceCode,
            @RequestParam("language") String language,
            @RequestParam(value = "stdin", required = false, defaultValue = "") String stdin,
            @RequestParam(value = "expected_output", required = false, defaultValue = "") String expectedOutput,
            @RequestParam(value = "wait", defaultValue = "true") boolean wait) {
        
        try {
            JudgeSubmissionResponse response = judgeService.submitCode(sourceCode, language, stdin, expectedOutput, wait);
            return ResultUtils.success(response);
        } catch (IllegalArgumentException e) {
            logger.error("提交代码评测失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持的编程语言: " + language);
        } catch (IOException e) {
            logger.error("提交代码评测失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "提交代码评测失败: " + e.getMessage());
        }
    }
    
    /**
     * 提交多文件代码进行评测
     * @param mainFile 主文件路径
     * @param additionalFiles 附加文件路径列表
     * @param compileScript 编译脚本
     * @param runScript 运行脚本
     * @param stdin 标准输入
     * @param expectedOutput 期望输出
     * @param wait 是否等待结果
     * @return 评测结果
     */
    @PostMapping("/submit-multi-files")
    public BaseResponse<JudgeSubmissionResponse> submitMultiFiles(
            @RequestParam("main_file") String mainFile,
            @RequestParam(value = "additional_files", required = false) List<String> additionalFiles,
            @RequestParam("compile_script") String compileScript,
            @RequestParam("run_script") String runScript,
            @RequestParam(value = "stdin", required = false, defaultValue = "") String stdin,
            @RequestParam(value = "expected_output", required = false, defaultValue = "") String expectedOutput,
            @RequestParam(value = "wait", defaultValue = "true") boolean wait) {
        
        try {
            JudgeSubmissionResponse response = judgeService.submitMultiFiles(
                    mainFile, additionalFiles, compileScript, runScript, stdin, expectedOutput, wait);
            return ResultUtils.success(response);
        } catch (IOException e) {
            logger.error("提交多文件代码评测失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "提交多文件代码评测失败: " + e.getMessage());
        }
    }
    
    /**
     * 批量提交代码进行评测
     * @param submissions 提交列表
     * @param wait 是否等待结果
     * @return 评测结果列表
     */
    @PostMapping("/batch")
    public BaseResponse<List<JudgeSubmissionResponse>> batchSubmitCode(
            @RequestBody List<JudgeSubmission> submissions,
            @RequestParam(value = "wait", defaultValue = "false") boolean wait) {
        
        try {
            List<JudgeSubmissionResponse> responses = judgeService.submitBatchCode(submissions, wait);
            return ResultUtils.success(responses);
        } catch (IOException e) {
            logger.error("批量提交代码评测失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "批量提交代码评测失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取评测结果
     * @param token 提交令牌
     * @return 评测结果
     */
    @GetMapping("/status/{token}")
    public BaseResponse<JudgeSubmissionResponse> getSubmissionStatus(
            @PathVariable String token,
            @RequestParam(value = "fields", required = false) String fields) {
        
        try {
            JudgeSubmissionResponse response;
            if (fields != null && !fields.isEmpty()) {
                response = judgeService.getSubmission(token, fields);
            } else {
                response = judgeService.getSubmission(token);
            }
            return ResultUtils.success(response);
        } catch (IOException e) {
            logger.error("获取评测结果失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取评测结果失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取批量评测结果
     * @param tokens 提交令牌列表
     * @param fields 需要返回的字段，多个字段用逗号分隔
     * @return 评测结果列表
     */
    @PostMapping("/batch-status")
    public BaseResponse<List<JudgeSubmissionResponse>> getBatchSubmissionStatus(
            @RequestBody List<String> tokens,
            @RequestParam(value = "fields", required = false) String fields) {
        
        try {
            List<JudgeSubmissionResponse> responses;
            if (fields != null && !fields.isEmpty()) {
                responses = judgeService.getBatchSubmissions(tokens, fields);
            } else {
                responses = judgeService.getBatchSubmissions(tokens);
            }
            return ResultUtils.success(responses);
        } catch (IOException e) {
            logger.error("获取批量评测结果失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取批量评测结果失败: " + e.getMessage());
        }
    }
    
    /**
     * 删除评测提交
     * @param token 提交令牌
     * @return 是否成功
     */
    @DeleteMapping("/submission/{token}")
    public BaseResponse<Boolean> deleteSubmission(@PathVariable String token) {
        try {
            boolean result = judgeService.deleteSubmission(token);
            return ResultUtils.success(result);
        } catch (IOException e) {
            logger.error("删除评测提交失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "删除评测提交失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取详细语言列表
     * @param all 是否包含归档语言，默认false
     * @return 语言列表
     */
    @GetMapping("/languages-detail")
    public BaseResponse<Object> getDetailedLanguages(
            @RequestParam(value = "all", defaultValue = "false") boolean all) {
        try {
            Object languages = judgeService.getLanguagesList(all);
            return ResultUtils.success(languages);
        } catch (IOException e) {
            logger.error("获取语言详细列表失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取语言详细列表失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取特定语言信息
     * @param languageId 语言ID
     * @return 语言信息
     */
    @GetMapping("/languages/{languageId}")
    public BaseResponse<Object> getLanguageInfo(@PathVariable int languageId) {
        try {
            Object language = judgeService.getLanguageInfo(languageId);
            return ResultUtils.success(language);
        } catch (IOException e) {
            logger.error("获取语言信息失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取语言信息失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取状态列表
     * @return 状态列表
     */
    @GetMapping("/statuses")
    public BaseResponse<Object> getStatusList() {
        try {
            Object statuses = judgeService.getStatusList();
            return ResultUtils.success(statuses);
        } catch (IOException e) {
            logger.error("获取状态列表失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取状态列表失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取系统信息
     * @return 系统信息
     */
    @GetMapping("/system-info")
    public BaseResponse<Object> getSystemInfo() {
        try {
            Object info = judgeService.getSystemInfo();
            return ResultUtils.success(info);
        } catch (IOException e) {
            logger.error("获取系统信息失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取系统信息失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取配置信息
     * @return 配置信息
     */
    @GetMapping("/config")
    public BaseResponse<Object> getConfigInfo() {
        try {
            Object config = judgeService.getConfigInfo();
            return ResultUtils.success(config);
        } catch (IOException e) {
            logger.error("获取配置信息失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取配置信息失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取统计信息
     * @param invalidateCache 是否刷新缓存
     * @return 统计信息
     */
    @GetMapping("/statistics")
    public BaseResponse<Object> getStatistics(
            @RequestParam(value = "invalidate_cache", defaultValue = "false") boolean invalidateCache) {
        try {
            Object statistics = judgeService.getStatistics(invalidateCache);
            return ResultUtils.success(statistics);
        } catch (IOException e) {
            logger.error("获取统计信息失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取统计信息失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取工作进程状态
     * @return 工作进程状态
     */
    @GetMapping("/workers")
    public BaseResponse<Object> getWorkers() {
        try {
            Object workers = judgeService.getWorkers();
            return ResultUtils.success(workers);
        } catch (IOException e) {
            logger.error("获取工作进程状态失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取工作进程状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取关于信息
     * @return 关于信息
     */
    @GetMapping("/about")
    public BaseResponse<Object> getAbout() {
        try {
            Object about = judgeService.getAbout();
            return ResultUtils.success(about);
        } catch (IOException e) {
            logger.error("获取关于信息失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取关于信息失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取版本信息
     * @return 版本信息
     */
    @GetMapping("/version")
    public BaseResponse<Object> getVersion() {
        try {
            Object version = judgeService.getVersion();
            return ResultUtils.success(version);
        } catch (IOException e) {
            logger.error("获取版本信息失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取版本信息失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取许可证信息
     * @return 许可证信息
     */
    @GetMapping("/license")
    public BaseResponse<Object> getLicense() {
        try {
            Object license = judgeService.getLicense();
            return ResultUtils.success(license);
        } catch (IOException e) {
            logger.error("获取许可证信息失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取许可证信息失败: " + e.getMessage());
        }
    }
    
    /**
     * 检查Judge0服务认证和授权状态
     * @return 服务状态
     */
    @GetMapping("/check-service")
    public BaseResponse<Map<String, Boolean>> checkJudgeService() {
        try {
            Map<String, Boolean> status = Map.of(
                "authentication", judgeService.checkAuthentication(),
                "authorization", judgeService.checkAuthorization()
            );
            return ResultUtils.success(status);
        } catch (Exception e) {
            logger.error("检查服务状态失败: {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "检查服务状态失败: " + e.getMessage());
        }
    }
} 